home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / MSJV7_2B.ARJ / OBJECT.C < prev    next >
C/C++ Source or Header  |  1992-03-01  |  45KB  |  1,169 lines

  1. /* 
  2.  * object.c - OLE object support routines 
  3.  *
  4.  * Created by Microsoft Corporation.
  5.  * (c) Copyright Microsoft Corp. 1990 - 1992  All Rights Reserved
  6.  */
  7.  
  8. //*** INCLUDES ****
  9.  
  10. #include <windows.h>                   //* WINDOWS
  11. #include <shellapi.h>                  //* SHELL
  12. #include <ole.h>                       //* OLE
  13.  
  14. #include "global.h"                    //* global variables and structures
  15. #include "stream.h"                    //* application includes:
  16. #include "object.h"
  17. #include "clidemo.h"
  18. #include "demorc.h"
  19. #include "utility.h"
  20. #include "dialog.h"
  21. #include "register.h"
  22.  
  23. #define  HIMETRIC_PER_INCH   2540      //* number HIMETRIC units per inch
  24.  
  25.  
  26. //*** VARIABLES ***
  27.  
  28. //*** Globals
  29. int     cOleWait     = 0;
  30.                     
  31. int     giXppli;                       //* pixels per logical inch along width
  32. int     giYppli;                       //* pixels per logical inch along height 
  33.  
  34.  
  35. /***************************************************************************
  36.  * CallBack()
  37.  *
  38.  * This routine will be called whenever an object has been changed, 
  39.  * saved, renamed, is being painted, or an  asynchronous operation has 
  40.  * completed. This routine is called by the OLE client DLL in the 
  41.  * above situations.  A pointer to this function is kept in the client
  42.  * vtbl.  It is our obligation as a client application to insure that a
  43.  * pointer to this procedure is in the vtbl.
  44.  *
  45.  * IMMPORTANT: notice that we are posting messages here rather that doing
  46.  * the work right away.  Well, this is done to avoid any possibility of
  47.  * getting into another dispatch message loop.  A MessageBox woul do this!
  48.  *
  49.  * Returns int - see below 
  50.  *
  51.  * The return value is generally ignored, except for these notifications:  
  52.  * OLE_QUERY_PAINT and  OLE_QUERY_RETRY. For these two notifications, 
  53.  * returning TRUE means continue the current operation(eg painting or retry)
  54.  * Returning FALSE means stop the current operation. This is useful as an 
  55.  * object which takes a long time to paint can be interrupted in order to 
  56.  * perform other operations.
  57.  ***************************************************************************/
  58.  
  59. int FAR PASCAL CallBack(               //* ENTRY:
  60.    LPOLECLIENT    lpClient,            //* client application pointer
  61.    OLE_NOTIFICATION flags,             //* notification code being sent
  62.    LPOLEOBJECT    lpObject             //* OLE object pointer
  63. ){                                     //* LOCAL:
  64.    APPITEMPTR     pItem;               //* application item pointer
  65.  
  66.                                  
  67.    pItem = (APPITEMPTR)LOWORD(lpClient);
  68.    switch (flags) 
  69.    {
  70.       case OLE_CLOSED:                 //* server has closed
  71.          if (!pItem->fVisible)
  72.          {
  73.             PostMessage(hwndFrame, WM_DELETE,(WORD)pItem,0L);
  74.             Dirty(DOC_UNDIRTY);
  75.          }
  76.          SetFocus( hwndFrame );
  77.          break;
  78.  
  79.       case OLE_SAVED:                  //* server has saved object
  80.       case OLE_CHANGED:                //* object has changes
  81.          cOleWait++;
  82.          pItem->fServerChangedBounds = pItem->fVisible = TRUE;
  83.          PostMessage(pItem->hwnd, WM_CHANGE, NULL, 0L);
  84.          break;
  85.  
  86.       case OLE_RELEASE:                //* notification that an asynchronous
  87.          ToggleBlockTimer(FALSE,NULL); //* toggle timer off
  88.          if (hRetry)
  89.             PostMessage(hRetry,WM_COMMAND,IDCANCEL,0L);
  90.  
  91.          if (cOleWait)                 //* operation has completed
  92.          {
  93.             pItem->fRetry = TRUE;
  94.             if (!--cOleWait)
  95.                Hourglass(FALSE);
  96.             Release(pItem);
  97.          } 
  98.          break;
  99.  
  100.       case OLE_QUERY_RETRY:          //* Continue retrying.
  101.          ToggleBlockTimer(FALSE,NULL);//* toggle timer off
  102.          if (!hRetry && pItem->fRetry)
  103.             PostMessage(hwndFrame,WM_RETRY,(WORD)pItem,0L);
  104.          return (pItem->fRetry);
  105.              
  106.       case OLE_QUERY_PAINT:          //* continue repainting
  107.          return TRUE;                //* a false return terminates either
  108.  
  109.         default:
  110.             break;
  111.     }
  112.     return 0;                          //* return value is ignored in 
  113.                                        //* most cases, see header
  114. }
  115.  
  116. /***************************************************************************
  117.  * Release()
  118.  *
  119.  * Check for an error on the OLE_RELEASE notification. 
  120.  **************************************************************************/
  121.  
  122. static void Release(                   //* ENTRY:
  123.    APPITEMPTR     pItem                //* Item pointer
  124. ){                                     //* LOCAL:
  125.    WORD           wParam;              //* error code parameter
  126.  
  127.    if ((wParam = OleQueryReleaseError(pItem->lpObject)) == OLE_OK) 
  128.       return;
  129.  
  130.    switch (OleQueryReleaseMethod(pItem->lpObject)) 
  131.    {
  132.       case OLE_LNKPASTE:
  133.          pItem->fVisible = FALSE;
  134.          break;
  135.  
  136.       case OLE_CREATEFROMTEMPLATE:
  137.       case OLE_CREATE:
  138.          pItem->fVisible = FALSE;
  139.          cOleWait++;
  140.          PostMessage(hwndFrame, WM_DELETE,(WORD)pItem,1L);
  141.          Dirty(DOC_UNDIRTY);
  142.    }
  143.                                   //* post a message to the main window
  144.                                   //* which will display a message box
  145.    PostMessage(hwndFrame,WM_ERROR,wParam,NULL);
  146.  
  147. }
  148.  
  149. /***************************************************************************
  150.  *  Error()
  151.  *
  152.  *  This function checks for error conditions
  153.  *  generated by OLE API callsFor OLE_WAIT_FOR_RELEASE,
  154.  *  we keep track of the number of objects waiting, when
  155.  *  this count is zero, it is safe to exit the application.
  156.  *
  157.  *  Returns OLESTATUS -  0 if OLE_WAIT_FOR_RELEASE or OLE_OK
  158.  *                       otherwise the OLESTATUS returned after an action
  159.  *                       is taken.
  160.  *************************************************************************/
  161.  
  162. OLESTATUS FAR Error(                   //* ENTRY
  163.    OLESTATUS      olestat              //* OLE status
  164. ){
  165.  
  166.    switch (olestat) 
  167.    {
  168.       case OLE_WAIT_FOR_RELEASE:
  169.          if (!cOleWait)
  170.             Hourglass(TRUE);
  171.          cOleWait++;                   //* increment wait count
  172.  
  173.       case OLE_OK:
  174.          return 0;
  175.  
  176.       case OLE_ERROR_STATIC:           //* static object
  177.          ErrorMessage(W_STATIC_OBJECT);
  178.          break;
  179.  
  180.       case OLE_ERROR_REQUEST_PICT:
  181.       case OLE_ERROR_ADVISE_RENAME:
  182.       case OLE_ERROR_DOVERB:
  183.       case OLE_ERROR_SHOW:
  184.       case OLE_ERROR_OPEN:
  185.       case OLE_ERROR_NETWORK:
  186.       case OLE_ERROR_ADVISE_PICT:
  187.       case OLE_ERROR_COMM:             //* Invalid links
  188.          InvalidLink();
  189.          break;
  190.  
  191.       case OLE_BUSY:
  192.          RetryMessage(NULL,RD_CANCEL);
  193.  
  194.       default:
  195.          break;
  196.     }
  197.     return olestat;
  198. }
  199.  
  200.  
  201. /****************************************************************************
  202.  * PreItemCreate()
  203.  * 
  204.  * This routine allocates an application item structure. A pointer to this 
  205.  * structure is passed as the client structure, therefore we need to 
  206.  * have a pointer to the vtbl as the first entry. We are doing this 
  207.  * to allow acess to the application item information during a OLE
  208.  * DLL callback.  This approach simplifies matters.
  209.  *
  210.  * Returns APPITEMPTR - a pointer to a new application item structure
  211.  *                      which can operate as a client structure.
  212.  ***************************************************************************/
  213.  
  214. APPITEMPTR FAR PreItemCreate(          //* ENTRY:
  215.    LPOLECLIENT    lpClient,            //* OLE client pointer
  216.    BOOL           fShow,               //* show/no-show flag
  217.    LHCLIENTDOC    lhcDoc               //* client document handle
  218. ){                                     //* LOCAL:
  219.    HANDLE         hitem;               //* temp handle for new item
  220.    APPITEMPTR     pItem;               //* application item pointer
  221.  
  222.  
  223.    if (hitem = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof(APPITEM)))
  224.       if (pItem = (APPITEMPTR)LocalLock(hitem))
  225.       {                                //* set the vtbl pointer
  226.          pItem->oleclient.lpvtbl     = lpClient->lpvtbl;
  227.          pItem->lpObjectUndo         = NULL;
  228.          pItem->fVisible             = fShow;
  229.          pItem->fServerChangedBounds = FALSE;
  230.          pItem->lhcDoc               = lhcDoc;
  231.  
  232.          return pItem;                 //* SUCCESS return
  233.       }
  234.  
  235.    ErrorMessage(E_FAILED_TO_ALLOC);
  236.    return NULL;                        //* ERROR return
  237.  
  238. }
  239.  
  240.  
  241. /***************************************************************************
  242.  * ItemWndProc()
  243.  *
  244.  * This function handles item window message processing.
  245.  * There is an item window for each OLE object. This was done to
  246.  * to simplify hit testing and repainting. These windows are child
  247.  * windows.
  248.  
  249.  * returns long - standard child routine
  250.  **************************************************************************/
  251.  
  252. long FAR PASCAL ItemWndProc(           //* ENTRY:
  253.    HWND           hwnd,                //* standard windows parameters
  254.    unsigned       msg, 
  255.    WORD           wParam, 
  256.    LONG           lParam
  257. ){                                     //* LOCAL:
  258.    static POINT   dragPt;              //* Mouse drag point 
  259.    static RECT    dragRect;            //* Mouse drag rectangle 
  260.    static BOOL    fCaptured;           //* captured flag
  261.    APPITEMPTR     pItem;               //* application item pointer
  262.    PAINTSTRUCT    ps;                  //* paint structure
  263.    POINT          pt;                  //* point
  264.    RECT           rc;                  //* bounding rectangle
  265.  
  266.    switch (msg) 
  267.    {     
  268.       case WM_SIZE:
  269.          if (pItem = (APPITEMPTR)GetWindowWord(hwnd,0))
  270.          {
  271.             if (!pItem->fServerChangedBounds && pItem->otObject == OT_EMBEDDED)
  272.                ObjSetBounds(pItem);
  273.             else
  274.                pItem->fServerChangedBounds = FALSE;
  275.          }
  276.          break;
  277.  
  278.       case WM_CHANGE:
  279.          --cOleWait;
  280.          pItem = (APPITEMPTR)GetWindowWord(hwnd,0);
  281.          if (!Error(OleQueryBounds(pItem->lpObject, &rc))) 
  282.          {
  283.             ConvertToClient(&rc);
  284.  
  285.             SetWindowPos(
  286.                hwnd, 
  287.                NULL, 
  288.                0, 
  289.                0,
  290.                rc.right - rc.left + 2*GetSystemMetrics(SM_CXFRAME),
  291.                rc.bottom - rc.top + 2*GetSystemMetrics(SM_CYFRAME),
  292.                SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME
  293.             );
  294.  
  295.             if (!pItem->fNew && !fLoadFile)
  296.                ShowNewWindow(pItem);
  297.             else
  298.                InvalidateRect(hwnd, NULL, TRUE);
  299.  
  300.             Dirty(DOC_DIRTY);
  301.          }
  302.          break;
  303.  
  304.       case WM_NCLBUTTONDOWN:
  305.          SetTopItem((APPITEMPTR)GetWindowWord(hwnd,0));
  306.          return (DefWindowProc(hwnd, msg, wParam, lParam));
  307.  
  308.       case WM_PAINT:
  309.          BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
  310.          GetClientRect(hwnd, &rc);
  311.          pItem = (APPITEMPTR)GetWindowWord(hwnd, 0);
  312.                                        //* Call OLE draw
  313.          Error(OleDraw(pItem->lpObject, ps.hdc, &rc, NULL, NULL));
  314.  
  315.          EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
  316.          break;
  317.  
  318.       case WM_LBUTTONDBLCLK:           //* execute a verb 
  319.          ANY_OBJECT_BUSY;
  320.          ExecuteVerb(OLEVERB_PRIMARY,(APPITEMPTR)GetWindowWord(hwnd,0));
  321.          break;
  322.  
  323.       case WM_LBUTTONDOWN:    
  324.          GetWindowRect(hwnd, (LPRECT)&dragRect);
  325.          ScreenToClient(hwndFrame, (LPPOINT)&dragRect);
  326.          ScreenToClient(hwndFrame, (LPPOINT)&dragRect.right);
  327.  
  328.          dragPt.x = LOWORD(lParam);
  329.          dragPt.y = HIWORD(lParam);
  330.  
  331.          ClientToScreen(hwnd, (LPPOINT)&dragPt);
  332.          ScreenToClient(hwndFrame, (LPPOINT)&dragPt);
  333.  
  334.          SetCapture(hwnd);
  335.          fCaptured = TRUE;
  336.          SetTopItem((APPITEMPTR)GetWindowWord(hwnd,0));
  337.          break;
  338.  
  339.       case WM_LBUTTONUP:
  340.          if (!fCaptured)
  341.                 break;
  342.          ReleaseCapture();
  343.          fCaptured = FALSE;
  344.          Dirty(DOC_DIRTY);
  345.          break;
  346.  
  347.       case WM_MOUSEMOVE:
  348.          if (!fCaptured)
  349.             break;
  350.          pt.x = LOWORD(lParam);
  351.          pt.y = HIWORD(lParam);
  352.  
  353.          ClientToScreen(hwnd, (LPPOINT)&pt);
  354.          ScreenToClient(hwndFrame, (LPPOINT)&pt);
  355.  
  356.          OffsetRect(
  357.                (LPRECT)&dragRect, 
  358.                pt.x - dragPt.x, 
  359.                pt.y - dragPt.y
  360.          );
  361.  
  362.          MoveWindow(
  363.             hwnd, 
  364.             dragRect.left, dragRect.top,
  365.             dragRect.right - dragRect.left,
  366.             dragRect.bottom - dragRect.top, TRUE
  367.          );
  368.  
  369.          dragPt.x = pt.x;
  370.          dragPt.y = pt.y;
  371.          break;
  372.    
  373.       default: 
  374.          return (DefWindowProc(hwnd, msg, wParam, lParam));
  375.    }
  376.    return 0L;
  377.  
  378. }
  379.  
  380. /****************************************************************************
  381.  * PostItemCreate()
  382.  *
  383.  * This function creates a child window which will contain the newly 
  384.  * created OLE object. A pointer to our item information is stored in the 
  385.  * extra bytes of this window. This is where we internally keep track
  386.  * of information related to the object as well as the
  387.  * pointer to the object for subsequent OLE API calls.  This routine is
  388.  * called after an OLE object has been created by the client library.
  389.  *
  390.  * Returns BOOL - TRUE if application item has been created.
  391.  ****************************************************************************/
  392.  
  393. BOOL FAR PostItemCreate(               //* ENTRY:
  394.    LPOLEOBJECT    lpObject,            //* OLE object pointer
  395.    long           otObject,            //* OLE object type
  396.    LPRECT         lprcObject,          //* object bounding rect
  397.    APPITEMPTR     pItem                //* application item pointer
  398. ){                                     //* LOCAL:
  399.    int            i;                   //* index
  400.    RECT           rc;                  //* bounding rectangle
  401.    char           pData[OBJECT_LINK_MAX];//* copy of link data
  402.  
  403.    if (lprcObject)                     //* if the size of the objects
  404.       rc = *lprcObject;                //* bounding rectangle is not
  405.    else if (OleQueryBounds(lpObject, &rc) == OLE_OK) 
  406.       ConvertToClient(&rc);
  407.    else 
  408.       SetRect(&rc, 0, 0, 0, 0);
  409.  
  410.    if (!(pItem->hwnd = CreateWindow(   //* Create the child window 
  411.          szItemClass, "",
  412.          WS_BORDER | WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME,
  413.          rc.left,rc.top,
  414.          rc.right - rc.left + 2 * GetSystemMetrics(SM_CXFRAME),
  415.          rc.bottom - rc.top + 2 * GetSystemMetrics(SM_CYFRAME),
  416.          hwndFrame, NULL, hInst, NULL
  417.    ))) goto Error;
  418.  
  419.                                        //* in windows extra bytes
  420.    SetWindowWord(pItem->hwnd, 0, (WORD)pItem);
  421.  
  422.    pItem->otObject = otObject;
  423.    pItem->lpObject = lpObject;
  424.    pItem->fRetry  = TRUE;
  425.  
  426.    if( pItem->otObject == OT_EMBEDDED )//* if object is embedded tell library
  427.    {                                   //* the container name and object name.
  428.       int cb = CBOBJNAMEMAX;           //* The name will be the server window title.
  429.       char sz[CBOBJNAMEMAX];           //* when the object is edited. 
  430.  
  431.       OleQueryName(lpObject, (LPSTR)sz, &cb );
  432.  
  433.       WaitForObject(pItem);
  434.       Error(OleSetHostNames(lpObject, (LPSTR)szAppName, (LPSTR)sz ));
  435.       WaitForObject(pItem);
  436.    }
  437.    else if (pItem->otObject == OT_LINK)//* if the object is linked  
  438.    {                                   //* retrieve update options
  439.  
  440.       WaitForObject(pItem);
  441.       if(Error(OleGetLinkUpdateOptions(pItem->lpObject, &pItem->uoObject)))
  442.          goto Error;
  443.       
  444.       if (ObjGetData(pItem,pData))
  445.       {
  446.          for (i=0; pData[i];i++);      //* Skip past the server name 
  447.          pItem->aLinkName = AddAtom(&pData[++i]);
  448.       } 
  449.       else
  450.          pItem->aLinkName = AddAtom("");
  451.    }
  452.    iObjects++;
  453.    Dirty(DOC_DIRTY);
  454.                                        //* a user interface recommendations.
  455.    return TRUE;                        //* SUCCESS return
  456.  
  457. Error:                                 //* ERROR Tag
  458.  
  459.    ErrorMessage(E_FAILED_TO_CREATE_CHILD_WINDOW);
  460.    FreeAppItem(pItem);
  461.    
  462.    return FALSE;                       //* ERROR return
  463.  
  464. }
  465.    
  466. /***************************************************************************
  467.  * ConvertToClient()
  468.  *
  469.  * This function will convert to client from himetric.
  470.  **************************************************************************/
  471.  
  472. void FAR ConvertToClient(              //* ENTRY:
  473.    LPRECT         lprc                 //* pointer to bounding rectangle
  474. ){                                     //* LOCAL
  475.  
  476.    //* If we have an empty rectangle then set the default size 
  477.    if (!(lprc->left || lprc->top || lprc->right || lprc->bottom))
  478.       SetRect(lprc, 0, 0, CXDEFAULT, CYDEFAULT);
  479.    else 
  480.    {
  481.       //* We got the himetric units, converts them to pixels now.     
  482.       lprc->right   = MulDiv (giXppli, (lprc->right - lprc->left),
  483.                           HIMETRIC_PER_INCH);
  484.                       
  485.       lprc->bottom  = MulDiv (giYppli, (lprc->top - lprc->bottom),
  486.                           HIMETRIC_PER_INCH);
  487.  
  488.       lprc->left    = 0;
  489.       lprc->top     = 0;      
  490.     }
  491. }
  492.  
  493. /***************************************************************************
  494.  * ObjInsert()
  495.  * 
  496.  * Query the user for object type to insert and insert the new OLE object
  497.  ***************************************************************************/
  498.  
  499. void FAR ObjInsert(                    //* ENTRY:
  500.    LHCLIENTDOC    lhcDoc,              //* OLE document handle              
  501.    LPOLECLIENT    lpClient             //* pointer to OLE client structure
  502. ){                                     //* LOCAL:   
  503.    FARPROC        lpfnInsertNew;       //* Insert New dialog bos instance thunk
  504.    LPOLEOBJECT    lpObject;            //* pointer to OLE object 
  505.    APPITEMPTR     pItem;               //* item pointer
  506.    char           szServerName[CBPATHMAX];//* Class name for OleCreate() 
  507.    char           szClassName[CBPATHMAX];//* Class name for OleCreate() 
  508.    char           szTmp[CBOBJNAMEMAX]; //* buffer to unique object name 
  509.     
  510.    lpfnInsertNew    = MakeProcInstance(fnInsertNew, hInst);
  511.  
  512.    if (DialogBoxParam(hInst, MAKEINTRESOURCE(DTCREATE),hwndFrame, 
  513.             lpfnInsertNew, (long)((LPSTR)szClassName)) != IDCANCEL)    
  514.    {
  515.       if (pItem = PreItemCreate(lpClient, FALSE, lhcDoc))
  516.       {
  517.          RegGetClassId(szServerName, szClassName);
  518.          pItem->aServer = AddAtom(szServerName);
  519.          if ( Error( OleCreate(STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient), 
  520.             (LPSTR)szClassName, lhcDoc,CreateNewUniqueName(szTmp), 
  521.             &lpObject,olerender_draw, 0))) 
  522.          {
  523.             ErrorMessage(E_FAILED_TO_CREATE_OBJECT);
  524.             FreeAppItem(pItem);
  525.          }
  526.          else
  527.             PostItemCreate(lpObject, OT_EMBEDDED, NULL, pItem);
  528.       }
  529.    }  
  530.  
  531.    FreeProcInstance(lpfnInsertNew);
  532.  
  533. }
  534.  
  535. /***************************************************************************
  536.  *  ObjDelete()
  537.  *
  538.  * Delete an OLE object. For this application, all OLE objects 
  539.  * are associated with a child window; therefore the window must be 
  540.  * destroyed.
  541.  *
  542.  * NOTE: There is one case when we call OleRelease and the other when
  543.  * we call OleDelete.  We call OleRelease when we are deregistering
  544.  * a document and OleDelete when removing an object from a document. 
  545.  **************************************************************************/
  546.  
  547. void FAR ObjDelete(                    //* ENTRY:
  548.    APPITEMPTR     pItem,               //* pointer to application item
  549.    BOOL           fDelete              //* delete or release flag
  550. ){                                     //* LOCAL:
  551.  
  552.    if (pItem->lpObjectUndo)
  553.    {
  554.       Error(OleDelete(pItem->lpObjectUndo));
  555.                                        //* wait for asynchronous operation
  556.       WaitForObject(pItem);
  557.    }
  558.  
  559.    if (fDelete ? Error(OleDelete(pItem->lpObject)) 
  560.                      : Error(OleRelease(pItem->lpObject)))
  561.    {
  562.       ErrorMessage(E_FAILED_TO_DELETE_OBJECT);
  563.       return;                          //* ERROR return
  564.    }
  565.  
  566.    if (pItem->fVisible)
  567.    {
  568.       ShowWindow(pItem->hwnd, SW_HIDE); 
  569.       pItem->fVisible = FALSE;
  570.    }
  571.                                        //* the operation has to complete
  572.    WaitForObject(pItem);               //* before the application structure
  573.   
  574.    FreeAppItem(pItem); 
  575.    iObjects--;
  576.  
  577. }   
  578.  
  579.  
  580. /***************************************************************************
  581.  *  ObjPaste()
  582.  *
  583.  *  This function obtains an object from the clipboard.
  584.  *  Handles both embedded and linked objects. An item window is
  585.  *  created for each new object.
  586.  *
  587.  *  Returns BOOL  - TRUE if object was pasted succesfully.
  588.  **************************************************************************/
  589.  
  590. void FAR ObjPaste(                     //* ENTRY:
  591.    BOOL           fPaste,              //* Paste/PasteLink flag 
  592.    LHCLIENTDOC    lhcDoc,              //* client document handle
  593.    LPOLECLIENT    lpClient             //* pointer to client
  594. ){                                     //* LOCAL:          
  595.    LPOLEOBJECT    lpObject;            //* object pointer
  596.    long           otObject;            //* object type
  597.    APPITEMPTR     pItem;               //* application item pointer
  598.    char           szTmp[CBOBJNAMEMAX]; //* temporary object name string
  599.  
  600.    if (!(pItem = PreItemCreate(lpClient, TRUE, lhcDoc)))
  601.       return;                          //* ERROR return
  602.        
  603.    if (!OpenClipboard(hwndFrame))
  604.       goto Error;                      //* ERROR jump
  605.  
  606.  
  607.    if (fPaste)                         //* PASTE the object. 
  608.    {                                   //* Try "StdFileEditing" protocol
  609.       if (Error(OleCreateFromClip(STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient),lhcDoc,
  610.          CreateNewUniqueName(szTmp),&lpObject, olerender_draw,0))) 
  611.       {
  612.                                        //* next try "Static" protocol
  613.          if (Error(OleCreateFromClip(
  614.                   STATICP, (LPOLECLIENT)&(pItem->oleclient), lhcDoc,
  615.                   CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0))) 
  616.             goto Error;               //* ERROR jump
  617.       }
  618.    } 
  619.    else 
  620.    {                                   //* LINK therefore must be 
  621.                                        // "STdFileEditing" protocol
  622.         if (Error(OleCreateLinkFromClip(
  623.             STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient), lhcDoc,
  624.             CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
  625.             goto Error;                //* ERROR jump
  626.    }
  627.  
  628.    OleQueryType(lpObject, &otObject);
  629.    CloseClipboard();
  630.  
  631.    if (!PostItemCreate(lpObject, otObject, NULL, pItem))
  632.       return;                          //* ERROR return
  633.  
  634.    ShowNewWindow(pItem);
  635.    return;                             //* SUCCESS return
  636.  
  637.  
  638. Error:                                 //* TAG Error
  639.  
  640.    ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED);
  641.    CloseClipboard();
  642.    FreeAppItem(pItem);
  643.    
  644.    return;                             //* ERROR return
  645.  
  646. }
  647.  
  648. /***************************************************************************
  649.  * ObjCopy()
  650.  *
  651.  * This function places an OLE object on the clipboard via the \
  652.  * OleCopyToClipboard() function.
  653.  *
  654.  * Returns BOOL - TRUE if object successfully placed on clipboard
  655.  **************************************************************************/
  656.  
  657. BOOL FAR ObjCopy(                      //* ENTRY:
  658.    APPITEMPTR     pItem                //* pointer to app item
  659. ){                                     //* LOCAL:
  660.    BOOL           fReturn = TRUE;      //* return value
  661.    
  662.    if (!OpenClipboard(hwndFrame)) 
  663.       return FALSE;                    //* ERROR return
  664.  
  665.    EmptyClipboard();
  666.  
  667.    if (Error(OleCopyToClipboard(pItem->lpObject)))
  668.       fReturn = FALSE;                 //* prepare for ERROR out
  669.  
  670.    CloseClipboard();
  671.    return fReturn;                     //* ERROR or SUCCESS
  672.  
  673. }
  674.  
  675. /***************************************************************************
  676.  *  ObjCreateFromTemplate()
  677.  *
  678.  *  Creates an embedded object from file.
  679.  **************************************************************************/
  680.  
  681. void FAR ObjCreateFromTemplate(        //* ENTRY:
  682.    LHCLIENTDOC    lhcDoc,              //* client document handle
  683.    LPOLECLIENT    lpClient             //* client vtbl. pointer
  684. ){                                     //* LOCAL:
  685.    LPOLEOBJECT    lpObject;            //* OLE object pointer
  686.    APPITEMPTR     pItem;               //* application item pointer
  687.    char           szTmp[CBOBJNAMEMAX]; //* temporary object name string
  688.    char           szFileName[CBPATHMAX];//* file name string
  689.  
  690.    *szFileName = NULL;
  691.  
  692.    if (!OfnGetName(hwndFrame, szFileName, IDM_INSERTFILE))
  693.       return;                          //* ERROR operation aborted by user
  694.  
  695.    if (!(pItem = PreItemCreate(lpClient, FALSE, lhcDoc)))
  696.       return;                          //* ERROR
  697.              
  698.    if (Error(OleCreateFromTemplate(STDFILEEDITING, (LPOLECLIENT)pItem, szFileName,
  699.          lhcDoc, CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
  700.    {
  701.       ErrorMessage(E_CREATE_FROM_TEMPLATE);
  702.       FreeAppItem(pItem);
  703.       return;                          //* ERROR
  704.    }
  705.  
  706.    PostItemCreate(lpObject, OT_EMBEDDED, NULL, pItem);
  707.  
  708. }                                      //* SUCCESS
  709.  
  710.  
  711. /****************************************************************************
  712.  * ObjGetData()
  713.  * 
  714.  * Get the object link data.  The data that is retrieved from OLE is copied
  715.  * into lpLinkData if lpLinkData is not NULL.  Otherwise, space is dynamically
  716.  * allocated or reallocated; space is allocated if pItem->lpLinkData is NULL
  717.  * otherwise the pointer is reallocated. The data is returned is freed if
  718.  * there has been an OLE_WARN_DELETE_DATA error.
  719.  ***************************************************************************/
  720.  
  721. BOOL FAR ObjGetData(                   //* ENTRY:
  722.    APPITEMPTR     pItem,               //* OLE object
  723.    LPSTR          lpLinkData           //* pointer to linkdata
  724. ){                                     //* LOCAL:
  725.    HANDLE         hData;               //* handle to OLE link data 
  726.    LPSTR          lpData;              //* pointer to OLE link data
  727.    LPSTR          lpWork;              //* copy of OLE link data
  728.    BOOL           fFree = FALSE;       //* free OLE memory flag
  729.    LONG           lSize;               //* size of OLE link data
  730.    int            i;
  731.    
  732.    switch (Error(OleGetData(pItem->lpObject, 
  733.       (pItem->otObject == OT_LINK ? vcfLink : vcfOwnerLink), &hData)))
  734.    {
  735.       case OLE_WARN_DELETE_DATA:
  736.          fFree = TRUE;
  737.       case OLE_OK:
  738.          if(lpData = GlobalLock(hData))
  739.          {
  740.                                        //* copy the link data to new buffer
  741.             lSize=SizeOfLinkData(lpData);
  742.             
  743.             if (!lpLinkData)
  744.             {
  745.                if (!pItem->lpLinkData)  //* allocate
  746.                   AllocLinkData(pItem,lSize);
  747.                else                     //* otherwise reallocate
  748.                   ReallocLinkData(pItem,lSize);
  749.                lpWork = pItem->lpLinkData;
  750.             }
  751.             else
  752.                lpWork = lpLinkData;
  753.  
  754.             if (lpWork)
  755.                for (i=0L; i<(int)lSize; i++)     
  756.                   *(lpWork+i)=*(lpData+i);
  757.  
  758.             GlobalUnlock(hData);       //* free the linked data as needed
  759.             if (fFree)
  760.                GlobalFree(hData);
  761.  
  762.             return TRUE;               //* SUCCESS      
  763.          }
  764.       default:
  765.          return FALSE;                 //* FAILURE
  766.    }   
  767.  
  768. }
  769.  
  770. /***************************************************************************
  771.  * ObjChangeLink()
  772.  *
  773.  * Change the linkdata.  This routine will change the document portion of
  774.  * link data to lpDoc.  The old linkdata is expected to be in 
  775.  * lpaItem->lpLinkData    
  776.  **************************************************************************/
  777.  
  778. void FAR ObjChangeLinkData(            //* ENTRY:
  779.    APPITEMPTR     pItem,               //* OLE object   
  780.    LPSTR          lpDoc                //* document name
  781. ){                                     //* LOCAL:
  782.    LONG           lSize;               //* used to link data size
  783.    LPSTR          lpLinkData;          //* OLE link data pointer
  784.    static char    pWork[OBJECT_LINK_MAX]; //* used to construct new link data
  785.    int            i;                   //* index
  786.   
  787.    pItem->aLinkName = AddAtom(lpDoc);
  788.  
  789.    for (
  790.       lpLinkData = pItem->lpLinkData, i=0; 
  791.       pWork[i] = *lpLinkData; 
  792.       lpLinkData++, i++
  793.    );
  794.                                        //* into working buffer.
  795.    lstrcpy((LPSTR)&pWork[++i],lpDoc);  //* copy new document name. 
  796.                                       
  797.    for (; pWork[i]; i++);              //* skip to end of document name
  798.    for (++lpLinkData;*lpLinkData;lpLinkData++);
  799.                                        //* copy item name.
  800.    lstrcpy((LPSTR)&pWork[++i],++lpLinkData);
  801.    for (; pWork[i]; i++);              //* skip to end of buffer
  802.                                        //* which is the end of item info.
  803.    pWork[++i] = NULL;                  //* add extra null.
  804.  
  805.    lSize = SizeOfLinkData(pWork);      //* reallocate space so there is 
  806.    ReallocLinkData(pItem,lSize);       //* a properly sized block of info
  807.                                        //* to send the linked data to the
  808.    if (lpLinkData = pItem->lpLinkData) //* OLE DLL.
  809.       for (i=0; i<(int)lSize; i++)     //* copy new linkdata into this space
  810.          *lpLinkData++ = pWork[i];
  811.    else
  812.       return;                          //* ERROR return
  813.     
  814.    Error(OleSetData(pItem->lpObject, vcfLink, 
  815.          (HANDLE)GlobalHandle(HIWORD(pItem->lpLinkData))));
  816.       
  817. }                                      //* SUCCESS return
  818.  
  819. /****************************************************************************
  820.  * ObjSaveUndo()
  821.  *
  822.  * Clone the OLE object so that any changes to object can be undone if the
  823.  * user choses to exit without update.                                        
  824.  ***************************************************************************/
  825.   
  826. void FAR ObjSaveUndo(                  //* ENTRY:
  827.    APPITEMPTR     pItem                //* application item
  828. ){                                     //* LOCAL:
  829.    char           szTmp[CBOBJNAMEMAX]; //* holder of object name
  830.    LPSTR          lpClone;             //* pointer to clond object name
  831.    int            i;                   //* index
  832.  
  833.    if (!pItem->lpObjectUndo)
  834.    {
  835.       i=CBOBJNAMEMAX;
  836.       OleQueryName(pItem->lpObject, szTmp, &i);
  837.                                        //* give clone a unique name by 
  838.                                        //* altering object name prefix.
  839.       for (lpClone = OBJCLONE, i=0; *lpClone; szTmp[i++] = *lpClone++);  
  840.  
  841.       if (Error(OleClone(pItem->lpObject, (LPOLECLIENT)pItem,
  842.          pItem->lhcDoc, szTmp, &(pItem->lpObjectUndo))))
  843.       return;                          //* ERROR return
  844.  
  845.       pItem->otObjectUndo  = pItem->otObject;
  846.       pItem->uoObjectUndo  = pItem->uoObject;
  847.       pItem->aLinkUndo     = pItem->aLinkName;
  848.  
  849.       GetClientRect(pItem->hwnd, &pItem->rect);
  850.  
  851.       if (OleQueryOpen(pItem->lpObject) == OLE_OK)
  852.          pItem->fOpen = TRUE;
  853.       
  854.    }
  855.  
  856. }                                      //* SUCCESS return
  857.  
  858. /****************************************************************************
  859.  * ObjUndo()
  860.  *
  861.  * Restore an object to its state before changes.  The lpObject Undo is a 
  862.  * clone to the original object with a different name, therefore, all we
  863.  * have to do is rename that object and ditch the changed object.
  864.  ***************************************************************************/
  865.   
  866. void FAR ObjUndo(                      //* ENTRY:
  867.    APPITEMPTR     pItem                //* application item
  868. ){                                     //* LOCAL:
  869.    char           szTmp[CBOBJNAMEMAX]; //* object name holder
  870.    int            i;                   //* index
  871.  
  872.    OleQueryName(pItem->lpObject, szTmp, &i);
  873.    if (Error(OleDelete(pItem->lpObject)))
  874.       return;                          //* ERROR return
  875.                                        //* reset app item vars
  876.    pItem->lpObject      = pItem->lpObjectUndo;      
  877.    pItem->otObject      = pItem->otObjectUndo;
  878.    pItem->uoObject      = pItem->uoObjectUndo;
  879.    pItem->aLinkName     = pItem->aLinkUndo;
  880.    pItem->lpObjectUndo  = (LPOLEOBJECT)NULL;
  881.    pItem->otObjectUndo  = (LONG)NULL;
  882.  
  883.    if (Error(OleRename(pItem->lpObject,szTmp)))
  884.       return;                          //* ERROR return
  885.  
  886.    if (pItem->fOpen)
  887.    {
  888.       Error(OleReconnect(pItem->lpObject));
  889.       pItem->fOpen = FALSE;
  890.    }
  891.  
  892.    SetWindowPos(
  893.       pItem->hwnd, 
  894.       NULL, 0, 0,
  895.       pItem->rect.right - pItem->rect.left + 2*GetSystemMetrics(SM_CXFRAME),
  896.       pItem->rect.bottom - pItem->rect.top + 2*GetSystemMetrics(SM_CYFRAME),
  897.       SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME
  898.    );
  899.  
  900.    InvalidateRect(pItem->hwnd,NULL,TRUE);
  901.  
  902. }                                      //* SUCCESS return
  903.  
  904.  
  905. /****************************************************************************
  906.  * ObjDelUndo()
  907.  *
  908.  * Delete the undo object if the user is happy with the changes he/she made.
  909.  ***************************************************************************/
  910.  
  911. void FAR ObjDelUndo(                   //* ENTRY:
  912.    APPITEMPTR     pItem                //* application item
  913. ){
  914.  
  915.    if (Error(OleDelete(pItem->lpObjectUndo)))
  916.       return;                          //* ERROR return
  917.  
  918.    pItem->lpObjectUndo = (LPOLEOBJECT)NULL;
  919.    pItem->otObjectUndo = (LONG)NULL;
  920.    DeleteAtom(pItem->aLinkUndo);
  921.    pItem->lpObjectUndo = NULL;
  922.    
  923. }                                      //* SUCCESS return
  924.  
  925. /****************************************************************************
  926.  * ObjFreeze()
  927.  *
  928.  * Convert an object to a static object.
  929.  ***************************************************************************/
  930.   
  931. void FAR ObjFreeze(                    //* ENTRY:
  932.    APPITEMPTR     pItem                //* application item
  933. ){                                     //* LOCAL:
  934.    char           szTmp[CBOBJNAMEMAX]; //* temporary object name
  935.    LPSTR          lpTemp;              //* temporary prefix string
  936.    LPOLEOBJECT    lpObjectTmp;         //* temporary object pointer
  937.    int            i;                   //* index
  938.  
  939.    i=CBOBJNAMEMAX;
  940.    OleQueryName(pItem->lpObject, szTmp, &i);
  941.                                        //* create a unique name by changing 
  942.                                        //* the object name prefix
  943.    for (lpTemp = OBJTEMP, i=0; *lpTemp; szTmp[i++] = *lpTemp++);  
  944.  
  945.                                        //* this API creates a static object
  946.    if (Error(OleObjectConvert(pItem->lpObject, STATICP, (LPOLECLIENT)pItem,
  947.       pItem->lhcDoc, szTmp, &lpObjectTmp)))
  948.       return;
  949.                                        //* delete old object
  950.    if (Error(OleDelete(pItem->lpObject)))
  951.       return;
  952.  
  953.    WaitForObject(pItem);  
  954.  
  955.    pItem->lpObject = lpObjectTmp;
  956.    pItem->otObject = OT_STATIC;
  957.    pItem->uoObject = -1L;
  958.  
  959.    for (lpTemp = OBJPREFIX, i=0; *lpTemp; szTmp[i++] = *lpTemp++);  
  960.    if (Error(OleRename(pItem->lpObject,szTmp)))
  961.       return;
  962.    
  963.    
  964. }
  965.  
  966. /***************************************************************************
  967.  *  ObjCreateWrap()
  968.  *
  969.  * Create a wrapped object from the drag and drop feature of the 3.1 shell.
  970.  * NOTE: We are assuming that only one file has been dropped.  See the SDK
  971.  * documentation for instructions on how to deal with multiple files.
  972.  ***************************************************************************/
  973.  
  974. void FAR ObjCreateWrap(                //* ENTRY:
  975.    HANDLE         hdrop,               //* handle to dropped object
  976.    LHCLIENTDOC    lhcDoc,              //* document handle
  977.    LPOLECLIENT    lpClient             //* pointer to client structure
  978. ){                                     //* LOCAL:
  979.    char           szDragDrop[CBPATHMAX];//* Drag and drop file name 
  980.    LPOLEOBJECT    lpObject;            //* pointer to OLE object 
  981.    POINT          pt;                  //* position of dropped object
  982.    RECT           rc;                  //* object size and position 
  983.    char           szTmp[CBOBJNAMEMAX]; //* buffer for unique object name 
  984.    APPITEMPTR     pItem;               //* application item pointer
  985.    int            x,y;                 //* icon sizes
  986.       
  987.    x = GetSystemMetrics(SM_CXICON) / 2;
  988.    y = GetSystemMetrics(SM_CYICON) / 2;
  989.                                        //* Get the drag and drop filename
  990.                                        //* position 
  991.    DragQueryPoint(hdrop, &pt);
  992.    DragQueryFile(hdrop, 0, szDragDrop, CBPATHMAX);
  993.    DragFinish(hdrop);
  994.  
  995.    SetRect(&rc, pt.x - x, pt.y - y, pt.x + x, pt.y + y);
  996.  
  997.    if (!(pItem = PreItemCreate(lpClient, TRUE, lhcDoc)))
  998.       return;                          //* ERROR return
  999.                                        //* create OLE object
  1000.    if (Error(OleCreateFromFile(STDFILEEDITING, (LPOLECLIENT)pItem, 
  1001.          "Package", szDragDrop, lhcDoc, CreateNewUniqueName(szTmp), 
  1002.          &lpObject, olerender_draw, 0)))
  1003.    {
  1004.       ErrorMessage(E_FAILED_TO_CREATE_OBJECT);
  1005.       FreeAppItem(pItem);
  1006.       return;                          //* ERROR return
  1007.    }
  1008.  
  1009.    if (PostItemCreate(lpObject, OT_EMBEDDED, &rc, pItem))    
  1010.       ShowNewWindow(pItem);
  1011.    
  1012. }                                      //* SUCCESS return
  1013.  
  1014. /***************************************************************************
  1015.  *  UpdateObjectMenuItem()
  1016.  *
  1017.  *  Add an object popup menu for the chosen object if multiple verbs exist.
  1018.  *  The registration system is used to determine which verbs exist for the
  1019.  *   given object. 
  1020.  **************************************************************************/
  1021.  
  1022. void FAR UpdateObjectMenuItem(         //* ENTRY:
  1023.    HMENU       hMenu                   //* main menu
  1024. ){                                     //* LOCAL
  1025.    int         cVerbs;                 //* verb
  1026.    APPITEMPTR  pItem;                  //* application item ponter
  1027.    DWORD       dwSize = KEYNAMESIZE;
  1028.    char        szClass[KEYNAMESIZE], szBuffer[200];
  1029.    char        szVerb[KEYNAMESIZE];
  1030.    HANDLE      hPopupNew=NULL;
  1031.    HKEY        hkeyTemp;
  1032.    char        pLinkData[OBJECT_LINK_MAX];
  1033.                                        //* delete current item and submenu 
  1034.    DeleteMenu(hMenu, POS_OBJECT, MF_BYPOSITION );
  1035.    
  1036.    if (!(pItem = GetTopItem()) )
  1037.       goto Error;                      //* ERROR jump
  1038.    else if (!pItem->fVisible)
  1039.       goto Error;                      //* ERROR jump
  1040.                                        //* if STATIC ?
  1041.    if ((pItem->otObject != OT_EMBEDDED) && (pItem->otObject != OT_LINK)) 
  1042.       goto Error;                      //* ERROR jump
  1043.  
  1044.    if (!ObjGetData(pItem, pLinkData))  //* get linkdata as key reg database
  1045.       goto Error;                      //* ERROR jump
  1046.                                        //* open reg database   
  1047.    if (RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hkeyTemp)) 
  1048.       goto Error;                      //* ERROR jump
  1049.                                        //* check if class is reg-db
  1050.    if (RegQueryValue(HKEY_CLASSES_ROOT, pLinkData, szClass, &dwSize))
  1051.    {
  1052.       RegCloseKey(hkeyTemp);
  1053.       goto Error;                      //* ERROR jump    
  1054.    }
  1055.  
  1056.    for (cVerbs=0; ;++cVerbs)           //* extract all verbs from reg-db
  1057.    {
  1058.       dwSize = KEYNAMESIZE;
  1059.       wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\verb\\%d",
  1060.                                      (LPSTR)pLinkData,cVerbs);
  1061.  
  1062.       if (RegQueryValue(HKEY_CLASSES_ROOT, szBuffer, szVerb, &dwSize))
  1063.          break;
  1064.  
  1065.       if (!hPopupNew)
  1066.          hPopupNew = CreatePopupMenu();
  1067.  
  1068.       InsertMenu(hPopupNew, -1, MF_BYPOSITION, IDM_VERBMIN+cVerbs, szVerb);
  1069.    }
  1070.  
  1071.    //* NOTE: For International versions the following  verb menu
  1072.    //* may need to be formatted differently.
  1073.  
  1074.    switch (cVerbs)                     //* determine how many verbs found
  1075.    {
  1076.       case 0:                          //* none
  1077.          wsprintf(szBuffer, "Edit %s %s", (LPSTR)szClass, (LPSTR)"&Object");
  1078.          InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, IDM_VERBMIN, szBuffer);
  1079.          break;
  1080.  
  1081.       case 1:                          //* one
  1082.          wsprintf(szBuffer, "%s %s %s", (LPSTR)szVerb, (LPSTR)szClass, 
  1083.             (LPSTR)"&Object");
  1084.          DestroyMenu(hPopupNew);
  1085.          InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, IDM_VERBMIN, szBuffer);
  1086.          break;
  1087.  
  1088.      default:                          //* > 1
  1089.          wsprintf(szBuffer, "%s %s", (LPSTR)szClass, (LPSTR)"&Object");
  1090.          InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION | MF_POPUP, hPopupNew, szBuffer);
  1091.          EnableMenuItem(hMenu, POS_OBJECT, MF_ENABLED|MF_BYPOSITION);
  1092.          break;           
  1093.    }
  1094.  
  1095.    RegCloseKey(hkeyTemp);              //* close reg-db
  1096.    return;                             //* SUCCESS return
  1097.  
  1098. Error:                                 //* ERROR tag
  1099.    
  1100.    InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, NULL, "&Object");
  1101.    EnableMenuItem(hMenu, POS_OBJECT, MF_GRAYED | MF_BYPOSITION);
  1102.  
  1103. }                                      //* ERROR return
  1104.  
  1105. /***************************************************************************
  1106.  *  ExecuteVerb()
  1107.  *
  1108.  *  Execute the verb for the given object.
  1109.  ***************************************************************************/
  1110.  
  1111. void FAR ExecuteVerb(                  //* ENTRY:
  1112.    int iVerb,                          //* verb
  1113.    APPITEMPTR pItem                    //* application item pointer
  1114. ){                                     //* LOCAL
  1115.    RECT        rc;                     //* holds client area bounding rect
  1116.  
  1117.    if (pItem->otObject == OT_STATIC)   //* if the object is static beep
  1118.    {
  1119.       ErrorMessage(W_STATIC_OBJECT);
  1120.       return;                          //* return
  1121.    }
  1122.                                        //* get cliet area rectangle
  1123.    GetClientRect(hwndFrame, (LPRECT)&rc);
  1124.                                        //* execute OLE verb
  1125.    if (Error(OleActivate(pItem->lpObject, iVerb, TRUE, TRUE, hwndFrame, &rc))) 
  1126.       return;
  1127.   
  1128.    WaitForObject(pItem);               //* wait for async. operation
  1129.  
  1130.  
  1131. }                                      //* SUCCESS return
  1132.  
  1133. /****************************************************************************
  1134.  * ObjSetBounds
  1135.  *
  1136.  * Set the object bounds.  The object bounds are the child windos bounding
  1137.  * rectangle.  OLE servers recieve need the bounding rectangle in HIMETRIC
  1138.  * coordinates.  So, we convert from screen coordinates to HIMETRIC.
  1139.  *
  1140.  * Returns BOOL - TRUE if successful.
  1141.  ***************************************************************************/
  1142.  
  1143. BOOL FAR ObjSetBounds(                 //* ENTRY:
  1144.    APPITEMPTR     pItem                //* application item pointer 
  1145. ){                                     //* LOCAL:
  1146.    RECT           itemRect;            //* bounding rectangle      
  1147.  
  1148.    GetWindowRect(pItem->hwnd,&itemRect);//* get item window react
  1149.  
  1150.    itemRect.right -= GetSystemMetrics(SM_CXFRAME);
  1151.    itemRect.left += GetSystemMetrics(SM_CXFRAME);
  1152.    itemRect.top += GetSystemMetrics(SM_CYFRAME);
  1153.    itemRect.bottom -= GetSystemMetrics(SM_CYFRAME);
  1154.  
  1155.    itemRect.right  = MulDiv ((itemRect.right - itemRect.left),
  1156.                         HIMETRIC_PER_INCH, giXppli);
  1157.    itemRect.bottom = - MulDiv((itemRect.bottom - itemRect.top),
  1158.                         HIMETRIC_PER_INCH, giYppli);    
  1159.    itemRect.top    = NULL;
  1160.    itemRect.left   = NULL;
  1161.                                        //* set the rect for the server
  1162.    if (Error(OleSetBounds(pItem->lpObject,(LPRECT)&itemRect)))
  1163.       return FALSE;                    //* ERROR return
  1164.  
  1165.    WaitForObject(pItem);               //* wait for async. operation
  1166.    return TRUE;                        //* SUCCESS return
  1167.  
  1168. }
  1169.